Let's check out the platform we're currently running on
import platform
print(platform.uname())
uname_result(system='Linux', node='409f01564ddd', release='5.10.104-linuxkit', version='#1 SMP Thu Mar 17 17:08:06 UTC 2022', machine='armv7l')
Hopefully that shows armv7l :)
Time to use this code. The example has a simple add() function we can use to check that the package
can be found and used.
import example as m
print(m.add(1, 2))
3
Incredible.
# print(m.add_quad([0, 1, 2, 3], [-1, -2, 4, 7]))
from plotly.subplots import make_subplots
import plotly.graph_objects as go
def plot(x, y, **kwargs):
fig = make_subplots()
fig.add_trace(go.Scatter(x=x, y=y))
fig.show()
Time to use the C++ implementation of the Magic Circle to generate a sine wave.
osc = m.MagicCircle()
sample_rate = 1_000.0
osc.set_freq(sample_rate / 256, sample_rate)
x = [float(i) for i in range(0, int(sample_rate))]
y = [osc.advance() for _ in x]
plot(x, y)
Here we generate 4 seconds of audio and add a player into this notebook.
from IPython.display import Audio
sample_rate = 44_100.
osc.reset()
osc.set_freq(440.0, sample_rate)
Audio([osc.advance() for _ in range(0, 4 * int(sample_rate))], rate=sample_rate)
For those who don't have perfect pitch, it might be useful to check out the actual frequency of this sine wave
import numpy as np
N = 20_000
osc.reset()
osc.set_freq(440.0, float(N))
y = [osc.advance() for _ in range(0, N)]
Y = [np.abs(c) / N for c in np.fft.rfft(y)]
freq = np.arange(len(Y)) * N / (2*len(Y))
plot(freq, Y)
Now let's have a look at the distortion processor. It has a configurable parameter, using plotly sliders we can demo it. We can start by creating a function to generate the sliding graph. In practice, this would be part of some sort of custom plotting package extension.
def sliding(x, renderer, values):
fig = make_subplots()
for v in values:
fig.add_trace(go.Scatter(visible=False, x=x, y=renderer(v)))
fig.data[1].visible = True
steps = []
for i in range(0, len(fig.data)):
step = dict(
method='update',
args=[{'visible': [False] * len(fig.data)}],
)
step['args'][0]['visible'][i] = True
steps.append(step)
fig.update_layout(height=400, sliders=[dict(
active=1,
pad={'t': 20},
steps=steps
)])
fig.show()
And here is the sliding graph used with the distortion
dist = m.Distortion()
x = np.linspace(-1., 1., 1_000)
gains = np.linspace(0.5, 6.5, 30)
def render_dist(gain):
dist.set_gain(gain)
return [dist.process(i) for i in x]
sliding(x, renderer=render_dist, values=gains)
Now let's distort that sine signal and see how it alters the signal while varying the amount of gain.
x = np.linspace(0, 4 * int(sample_rate))
def render_with_dist(gain):
osc.reset()
osc.set_freq(sample_rate / 16, sample_rate)
dist.set_gain(gain)
return [dist.process(osc.advance()) for _ in x]
sliding(x, renderer=render_with_dist, values=gains)
import numpy as np
def render_freqz_with_dist(gain):
osc.reset()
osc.set_freq(440.0, float(N))
dist.set_gain(gain)
y = [dist.process(osc.advance()) for _ in range(0, N)]
return [np.abs(c) / N for c in np.fft.rfft(y)]
sliding(freq, renderer=render_freqz_with_dist, values=gains)